/**
 * 获取access_token
 *      是什么？微信调用接口全局唯一凭据
 *      特点：唯一的，有效期为2小时，有权限每天2000次
 *
 * 请求地址：（get请求）
 *  https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
 *
 * 设计思路
 *  1.首次本地没有，发送请求获取access_token，保存下来（本地文件）
 *  2.第二次或以后：先去本地读取文件，判读是否过期（过期：重新获取，并保存；没过期：直接使用）
 *
 *  request-promise-native，返回值是一个promise对象
 *
 */

const rpn = require('request-promise-native');
const {writeFile, readFile} = require('fs');

const {appID, appsecret} = require('../config/index');

class Wechat {
    constructor() {

    }

    // 请求access_token
    getAccessToken() {
        const url = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${appID}&secret=${appsecret}`;
        // 发送请求
        return new Promise((resolve, reject) => {
            rpn({
                method: 'GET',
                url,
                json: true
            })
                .then(res => {
                    console.log(res);
                    /**
                     {
                         access_token: 'xxxxxxx',
                         expires_in: 7200
                     }
                     */
                    // 设置access_token的过期时间
                    res.expires_in = Date.now() + (res.expires_in - 300) * 1000;

                    resolve(res);

                })
                .catch(err => {
                    console.log(err);
                    reject('getAccessToken出错：' + err);
                });
        });
    }

    // 保存access_token
    saveAccessToken(data) {
        return new Promise((resolve, reject) => {
            writeFile('./accessToken.txt', JSON.stringify(data), err => {
                if (!err) {
                    console.log("文件保存成功...");
                    resolve();
                } else {
                    reject('saveAccessToken出错：' + err);
                }
            });
        });
    }

    // 读取access_token
    readAccessToken() {
        return new Promise((resolve, reject) => {
            readFile('./accessToken.txt', (err, data) => {
                if (!err) {
                    console.log("文件读取成功...");
                    resolve(JSON.parse(data));
                } else {
                    reject('readAccessToken出错：' + err);
                }
            });
        });
    }

    // 判断access_token是否有效
    isValidAccessToken(data) {
        if (!data && !data.access_token && !data.expires_in) {
            return false;
        }
        if (data.expires_in < Date.now()) {
            return false;
        }
        return true;
    }

    // 获取有效的access_token
    fetchAccessToken() {
        if (this.access_token && this.expires_in && this.isValidAccessToken(this)) {
            return Promise.resolve({
                access_token: this.access_token,
                expires_in: this.expires_in
            });
        }
        return this.readAccessToken()
            .then(async res => {
                if (this.isValidAccessToken(res)) {
                    return Promise.resolve(res);
                } else {
                    const res = await this.getAccessToken();
                    await this.saveAccessToken(res);
                    return Promise.resolve(res);
                }
            })
            .catch(async err => {
                const res = await this.getAccessToken();
                await this.saveAccessToken(res);
                return Promise.resolve(res);
            })
            .then(res => {
                this.access_token = res.access_token;
                this.expires_in = res.expires_in;
                return Promise.resolve(res);
            })
    }
}

const wechat = new Wechat();

const result = new Promise((resolve, reject) => {
    wechat.readAccessToken()
        .then(res => {
            if (wechat.isValidAccessToken(res)) {
                resolve(res);
            } else {
                wechat.getAccessToken()
                    .then(res => {
                        wechat.saveAccessToken(res)
                            .then(() => {
                                resolve(res);
                            })
                    });
            }
        })
        .catch(err => {
            wechat.getAccessToken()
                .then(res => {
                    wechat.saveAccessToken(res)
                        .then(() => {
                            resolve(res);
                        })
                });
        })
})

console.log(result);

console.log(wechat.fetchAccessToken());
